import logging
import time

from django.views import View
from django.http import JsonResponse, FileResponse
from django.core.files.storage import storages
from django.conf import settings
from django.http import HttpResponseBadRequest
from django_q.tasks import async_task, result
from django_q.conf import logger

from ..models import (
    ImageRecognition,
    QandA,
)

# from .llm import (
#     decide_in_outs,
#     chat,
#     get_indexs,
#     write_indexs,
# )
from . import llm, ocr

hash_storage = storages["hash"]


def update(qa, status):
    qa.status = status
    qa.save()
    logger.info(f"{qa.status=}")


class GetQA(View):
    def _qa2resp(self, qa):
        resp = {
            "status": 0,
            "msg": "",
            "data": {
                "question": qa.question,
                "answer": qa.answer if qa.answer else f"{qa.status}",
                "autorefresh": not bool(qa.answer),
            },
        }
        return JsonResponse(resp)

    def _getqabyid(self, qa_id):
        if qa_id == 0:
            return None, JsonResponse(
                {
                    "status": 0,
                    "msg": "dumb item",
                    "data": {"autorefresh": False},
                }
            )
        else:
            try:
                qa = QandA.objects.get(id=qa_id)
            except QandA.DoesNotExist as e:
                return None, JsonResponse(
                    {
                        "status": -1,
                        "msg": str(e),
                        "data": {"autorefresh": False},
                    }
                )
        return qa, None

    @staticmethod
    def task(qa):
        update(qa, status="正在准备数据索引……")
        chat_id, conversation_id = llm.create_chat(qa.question)
        try:
            in_outs = llm.decide_in_outs(qa.question, mock=True)
            for item, value in in_outs.items():
                setattr(qa, item, value)
            qa.save()
            indexs = []
            for k, v in in_outs.items():
                if v and k.startswith("in"):
                    index = llm.get_index(name=k[3:])
                    indexs.append(index)
        except Exception as e:
            update(qa, status=f"错误：{e}")
            return

        update(qa, status="正在生成回答……")
        try:
            for i in range(30):
                time.sleep(5)
                status = llm.check_chat(chat_id, conversation_id)
                if status in ["completed", "failed", "requires_action"]:
                    break
            answer = llm.get_chat(chat_id, conversation_id)
            qa.answer = answer
            qa.save()
        except Exception as e:
            update(qa, status=f"错误：{e}")
            return

        update(qa, status="正在回写索引……")
        try:
            llm.write_indexs(qa.answer, indexs, mock=True)
        except Exception as e:
            update(qa, status=f"错误：{e}")
            return

        update(qa, status="完成")

    def get(self, request, qa_id, *args, **kwargs):
        print(f"{qa_id=}")
        qa, resp = self._getqabyid(qa_id)
        if resp:
            return resp
        if qa.status == "waiting":
            update(qa, status="正在排队中……")
            logger.info(f"{qa.status=}")
            async_task(GetQA.task, qa)
        return self._qa2resp(qa)


class ChatText(View):
    def post(self, request, *args, **kwargs):
        print("chattext")
        print(f"{request.POST=}")
        question = request.POST["textarea"]
        qa = QandA(question=question)
        qa.save()
        return JsonResponse({"qa_id": qa.id})


class ChatImage(View):
    @staticmethod
    def image_recognition_task(img, ocr_func):
        path = hash_storage.path(img.name)
        img.res_json = ocr_func(path)
        try:
            img.save()
        except Exception as e:
            print("##### Exception #####")
            print(e)

    def post(self, request, *args, **kwargs):
        print("chatreport")
        print(f"{request.POST=}")
        names = request.POST["image"].split(",")
        img_type = request.POST["img_type"]
        img_type2fields = {
            "medical_report_detection": {
                "question": "帮我解读一下这个检验报告单：",
                "out_symptom": True,
            },
            "health_report": {
                "question": "帮我解读一下这个诊断报告单：",
                "in_medical_handbook": True,
                "out_symptom": True,
            },
            "case_history": {
                "question": "帮我解读一下这个病历：",
                "out_symptom": True,
            },
            "medicine": {
                "question": "帮我解读一下这个药品是什么：",
                "in_pharmacopoeia_western": True,
                "in_pharmacopoeia_traditional_chinese": True,
            },
        }
        img_type2ocr = {
            "medical_report_detection": ocr.mock,
            "health_report": ocr.mock,
            "case_history": ocr.mock,
            "medicine": ocr.mock,
        }
        if img_type not in img_type2fields:
            return HttpResponseBadRequest("invalid img_type")
        qa = QandA(**(img_type2fields[img_type]))
        qa.save()

        for name in names:
            prefix = "/mydoctor/api/file/"
            if name.startswith(name):
                name = name[len(prefix) :]
            try:
                img = ImageRecognition.objects.get(name=name)
            except ImageRecognition.DoesNotExist:
                img = ImageRecognition()
                img.name = name
                img.img_type = img_type
                ocr_func = img_type2ocr[img_type]
                img.task_id = async_task(
                    ChatImage.image_recognition_task, img, ocr_func
                )
                img.save()
            qa.imgs.add(img)
        qa.save()
        return JsonResponse({"qa_id": qa.id})


class UploadFile(View):
    def post(self, request, *args, **kwargs):
        print(f"{request.FILES=}")
        file = request.FILES["file"]
        path = hash_storage.save(None, file)
        return JsonResponse(
            {
                "status": 0,
                "msg": f"{path=}",
                "data": {
                    "value": "/mydoctor/api/file/" + path,
                },
            }
        )


class FileView(View):
    def get(self, request, *args, **kwargs):
        return FileResponse(hash_storage.open(kwargs["name"]))
